package com.biscuit.page.basicservice.interceptor;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.biscuit.page.basicservice.conf.handler.RequestContextHandler;
import com.biscuit.page.basicservice.conf.handler.UserContextHandler;
import com.biscuit.page.basicservice.model.context.UserContext;
import com.biscuit.page.basicservice.model.enums.BaseResponseEnum;
import com.biscuit.page.basicservice.service.AuthorizationService;
import com.biscuit.page.basicservice.utils.BaseExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 授权校验拦截器
 *
 * @author mazihao
 * @createTime 2024/3/30 10:56
 */
@Slf4j
@Component
public class AuthorizationInterceptor implements HandlerInterceptor {

    @Resource
    private AuthorizationService authorizationService;

    @Override
    public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        log.info("{} - {}", request.getRequestURL().toString(), request.getMethod());

        // 判断是否为跨域请求，跨域直接放行
        if (RequestContextHandler.getContext().getIsOptions()) {
            log.info("本次请求为跨域处理预请求，直接放行");
            return true;
        }

        // 直接从全局上下文对象中获取用户信息
        UserContext context = UserContextHandler.getContext();

        // 判断用户信息是否存在，用户信息存在则直接放行即可
        try {
            if (Objects.nonNull(context)) {
                return true;
            }
        } catch (Exception e) {
            log.error("AuthorizationInterceptor 从用户信息全局上下文对象中获取用户信息失败，message -> {}", e.getMessage());
        }

        // 从请求头中获取 token
        String authorization = request.getHeader("Authorization");

        // 校验 token 是否为空
        BaseExceptionUtil.throwException(StringUtils.isNotBlank(authorization), "用户未登录，请先进行登录", BaseResponseEnum.ERROR_UNAUTHORIZED);

        // 校验 Token 合法性，合法则返回 null，不合法返回对应响应信息 JSON 字符串
        String resultJson = this.authorizationService.checkToken(authorization);

        // 异常则将信息写入响应返回，并拒绝拦截器放行
        log.error("AuthorizationInterceptor Token 不合法，用户未授权，message -> {}", resultJson);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.getWriter().write(resultJson);
        return false;
    }

}
